package com.syh.jn.scm.service.impl.supplier.base.goods;

import cn.redscarf.commons.util.exception.IllegalParameterException;
import cn.redscarf.commons.util.other.ExtStringUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.supplier.entity.base.goods.GoodsCategory;
import com.syh.jn.scm.domain.supplier.repository.base.goods.GoodsCategoryRepository;
import com.syh.jn.scm.dto.supplier.base.goods.goodsCate.GoodsCategoryMto;
import com.syh.jn.scm.dto.supplier.base.goods.goodsCate.GoodsCategorySto;
import com.syh.jn.scm.dto.supplier.base.goods.goodsCate.GoodsCategoryVo;
import com.syh.jn.scm.service.api.supplier.base.goods.GoodsCategoryService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class GoodsCategoryServiceImpl extends AbstractServiceImpl<GoodsCategorySto, GoodsCategoryMto, GoodsCategoryVo, GoodsCategory, Long> implements GoodsCategoryService {

  @Autowired
  private GoodsCategoryRepository goodsCategoryRepository;


  @Override
  protected AggregateRepository<GoodsCategory, Long> getAggregateRepository() {
    return goodsCategoryRepository;
  }

  /**
   * 保存对象
   *
   * @param sto
   * @return
   */
  @Override
  public Long save(GoodsCategorySto sto) {
    GoodsCategory goodsCate = new GoodsCategory(sto);
    goodsCategoryRepository.add(goodsCate);
    return goodsCate.getId();
  }

  /**
   * 虚拟父类id上传保存 会以map内的参数来处理父子类关系
   *
   * @param mapStoList
   * @return
   */
  @Override
  public List<Long> batchSaveWithVirtualId(List<Map<String, String>> mapStoList) {
    List<Long> ids = new ArrayList<>();
    Map<String, Long> savedMap = new HashMap();
    // 首先存储顶级分类
    mapStoList.forEach(item -> {
      if (ExtStringUtils.isBlank(item.get("supId"))) {
        GoodsCategorySto sto = GoodsCategorySto.builder()
                .name(item.get("name"))
                .orderLevel(ExtStringUtils.isEmpty(item.get("orderLevel")) ? null : Double.valueOf(item.get("orderLevel")).intValue())
                .businessEntityId(Long.valueOf(item.get("businessEntityId")))
                .build();
        // 真实数据库id
        Long realId = this.save(sto);
        ids.add(realId);
        savedMap.put(item.get("id"), realId);
      }
    });
    //清除掉已经保存的分类
    mapStoList = mapStoList.stream().filter(filterItem -> {
      return !savedMap.containsKey(filterItem.get("id"));
    }).collect(Collectors.toList());

    //递归不超5层  其实一般分类超3层都是不合理的设计了
    short reduceLevel = 0;
    if (!mapStoList.isEmpty()) {
      this.reduceSaveChildren(mapStoList, savedMap, ids, reduceLevel);
    }

    return ids;
  }

  /**
   * 递归保存子类
   *
   * @param mapStoList  需要保存的列表 当它size为0的时候就应该终止了
   * @param savedMap    已经保存的列表，使用于父子类配对
   * @param ids         已经保存的id列表
   * @param reduceLevel 递归层次 避免死循环，当supId字段的找不到父类时就会死循环了 这时候应该抛出异常
   * @return
   */
  private void reduceSaveChildren(List<Map<String, String>> mapStoList, Map<String, Long> savedMap, List<Long> ids, short reduceLevel) {
    if (reduceLevel > 5) {
      throw new IllegalParameterException("父子类层次超过5层，或者存在上级id不存在的分类");
    }

    mapStoList.forEach(item -> {
      if (savedMap.containsKey(item.get("supId"))) {
        GoodsCategorySto sto = GoodsCategorySto.builder()
                .name(item.get("name"))
                .supId(Long.valueOf(savedMap.get(item.get("supId"))))
                .orderLevel(ExtStringUtils.isEmpty(item.get("orderLevel")) ? null : Double.valueOf(item.get("orderLevel")).intValue())
                .businessEntityId(Long.valueOf(item.get("businessEntityId")))
                .build();
        // 真实数据库id
        Long realId = this.save(sto);
        ids.add(realId);
        savedMap.put(item.get("id"), realId);
      }
    });
    mapStoList = mapStoList.stream().filter(filterItem -> {
      return !savedMap.containsKey(filterItem.get("id"));
    }).collect(Collectors.toList());

    if (!mapStoList.isEmpty()) {
      ++reduceLevel;
      this.reduceSaveChildren(mapStoList, savedMap, ids, reduceLevel);
    } else {
      return;
    }
  }

  /**
   * 启用分类
   *
   * @param id
   */
  @Override
  public void enabled(Long id) {
    GoodsCategory goodsCate = goodsCategoryRepository.getById(id);
    goodsCate.enabled();
    if (goodsCate.getFatherCategorys() != null) updateFatherCates(goodsCate.getFatherCategorys());
    goodsCategoryRepository.update(goodsCate);
  }

  /**
   * 修改对象
   *
   * @param mto
   * @return
   */
  @Override
  public void update(GoodsCategoryMto mto) {
    GoodsCategory goodsCate = goodsCategoryRepository.getById(mto.getId());
    goodsCate.modify(mto);
    goodsCategoryRepository.update(goodsCate);
  }

  /**
   * 停用分类
   *
   * @param id
   */
  @Override
  public void disabled(Long id) {
    GoodsCategory goodsCate = goodsCategoryRepository.getById(id);
    goodsCate.disabled();
    updateSubCates(goodsCate.getSubCategorys());
    goodsCategoryRepository.update(goodsCate);
  }

  /**
   * 更新父分类状态
   *
   * @param fatherCates
   */
  public void updateFatherCates(GoodsCategory fatherCates) {
    if (fatherCates.getFatherCategorys() != null) {
      updateFatherCates(fatherCates.getFatherCategorys());
    }
    goodsCategoryRepository.update(fatherCates);
  }

  /**
   * 更新子分类状态
   *
   * @param subCates
   */
  public void updateSubCates(List<GoodsCategory> subCates) {
    subCates.forEach(subCate -> {
//      updateSubCates(subCate.getSubCategorys());
      goodsCategoryRepository.update(subCate);
    });
  }

  /**
   * 根据id删除对象
   *
   * @param id
   */
  @Override
  public void delete(Long id) {
    GoodsCategory goodsCate = goodsCategoryRepository.getById(id);
    goodsCate.destroy();
    goodsCategoryRepository.remove(goodsCate);
  }
}
